import { PrismaClient } from '@prisma/client';
import * as http from 'http';
import * as https from 'https';
import * as path from 'path';
import { randomUUID } from 'crypto';
import { uploadFile } from '../src/lib/storage';

const prisma = new PrismaClient();

// 站点数据（初始 12 个），分类按主题分组
const WEBSITES: Array<{ name: string; url: string; description: string; category: string }> = [
  {
    name: 'AI创作家',
    url: 'http://ai.chiyingapp.com/',
    description:
      '一个综合型 AI 助手工具：支持 AI 问答、智能写作、AI 专业训练、代码助手、AI 娱乐、AI 绘画、AI 语音等几十种功能。',
    category: 'AI 工具与写作',
  },
  {
    name: 'The Useless Web',
    url: 'http://theuselessweb.com/',
    description:
      '随机跳转到各种奇奇怪怪的无聊网页，每次点击 please 都会进入不同的有趣页面。',
    category: '趣味网站',
  },
  {
    name: 'Skyline Webcams',
    url: 'http://skylinewebcams.com/',
    description:
      '全球公开的高清实况摄像头，涵盖城市风光、海滩、风景、码头、滑雪场、动物、湖泊等类别，并提供当地天气。',
    category: '实况摄像头',
  },
  {
    name: 'MyFreeMP3',
    url: 'http://tools.liumingye.cn/music',
    description: '音乐在线播放与免费下载，支持搜索与推荐歌单/艺人/单曲。',
    category: '音乐',
  },
  {
    name: '模板王',
    url: 'http://www.mobanwang.com/',
    description:
      '中文字体与模板资源网站，包含免费商用字体、艺术字体，以及网页模板、PPT 模板等常用办公资源。',
    category: '字体与模板',
  },
  {
    name: 'Gallerix Asia',
    url: 'http://gallerix.asia/',
    description:
      '加勒里克斯在线博物馆，收录 17 万幅绘画作品，含蒙娜丽莎、向日葵、戴珍珠耳环的少女等世界名画。',
    category: '艺术博物馆',
  },
  {
    name: 'AirPano',
    url: 'http://airpano.com/',
    description:
      '由俄罗斯团队提供的世界各地景点全景图片与视频，画质清晰，可自由缩放与调整角度，沉浸式体验。',
    category: '全景与航拍',
  },
  {
    name: '自由钢琴 Autopiano',
    url: 'http://autopiano.cn/',
    description:
      '在线弹钢琴，键位支持键盘字母或鼠标点击；提供乐谱与演奏示例，并支持多种乐器（小提琴/竖琴/口琴/贝斯/爵士等）。',
    category: '在线乐器',
  },
  {
    name: '改图鸭 AI 绘画',
    url: 'http://gaituya.com/aiimg/',
    description:
      '简单好用的 AI 绘画工具，提供二次元、真实 3D、炫彩插画、艺术创想、自然风景等模型；基础生图目前免费不限次数。',
    category: 'AI 绘画',
  },
  {
    name: 'Pixabay（CC0 入口）',
    url: 'https://www.cc0.cn/image/pixabay/',
    description:
      '国外无版权图片素材站，涵盖人物、动物、风景等多个领域，免费高质量图片资源。',
    category: '图片素材',
  },
  {
    name: 'Canva（可画）',
    url: 'https://www.canva.cn/',
    description:
      '海报与设计模板丰富，选好模板后在右侧编辑文字即可快速生成作品，提升设计效率。',
    category: '海报设计',
  },
  {
    name: 'Khroma',
    url: 'http://khroma.co/',
    description:
      'AI 配色网站，支持个性化挑选喜欢颜色后生成配色方案。',
    category: '配色工具',
  },
];

// 统一 HTTP(S) 下载为 Buffer，并返回 content-type（支持最多 5 次重定向）
function downloadToBuffer(url: string): Promise<{ buffer: Buffer; contentType: string | null } | null> {
  return new Promise((resolve) => {
    const redirectLimit = 5;
    const doGet = (u: string, depth: number) => {
      try {
        const client = u.startsWith('https:') ? https : http;
        const req = client.get(u, (res) => {
          if (!res) {
            resolve(null);
            return;
          }
          const status = res.statusCode || 0;
          const location = res.headers.location || '';

          if (status >= 300 && status < 400 && location && depth < redirectLimit) {
            try {
              const nextUrl = new URL(location, u).toString();
              // 丢弃当前响应体，继续请求重定向后的地址
              res.resume();
              doGet(nextUrl, depth + 1);
              return;
            } catch {
              // 无法解析重定向地址，视为失败
              res.resume();
              resolve(null);
              return;
            }
          }

          if (status >= 400) {
            res.resume();
            resolve(null);
            return;
          }

          const chunks: Buffer[] = [];
          res.on('data', (chunk) => chunks.push(chunk as Buffer));
          res.on('end', () => {
            const buffer = Buffer.concat(chunks);
            const contentType = res.headers['content-type'] || null;
            resolve({
              buffer,
              contentType:
                typeof contentType === 'string'
                  ? contentType
                  : Array.isArray(contentType)
                    ? contentType[0]
                    : null,
            });
          });
        });
        req.on('error', () => resolve(null));
      } catch {
        resolve(null);
      }
    };

    doGet(url, 0);
  });
}

// 下载文本（HTML）
async function downloadText(url: string): Promise<string | null> {
  const result = await downloadToBuffer(url);
  if (!result) return null;
  try {
    return result.buffer.toString('utf-8');
  } catch {
    return null;
  }
}

// 解析站点 icon 地址（复用 API 路由中的逻辑）
function resolveIconUrl(html: string, siteUrl: string): string {
  try {
    const origin = new URL(siteUrl).origin;
    const linkIconRegex = /<link[^>]+rel=["']?(?:shortcut\s+icon|icon|apple-touch-icon(?:-precomposed)?)["']?[^>]*href=["']?([^"'>\s]+)/ig;
    const candidates: string[] = [];
    let match: RegExpExecArray | null;
    while ((match = linkIconRegex.exec(html)) !== null) {
      const href = match[1];
      try {
        candidates.push(new URL(href, origin).toString());
      } catch {}
    }
    if (candidates.length > 0) return candidates[0];

    const ogImageRegex = /<meta[^>]+property=["']?og:image["']?[^>]*content=["']?([^"'>\s]+)/i;
    const ogMatch = ogImageRegex.exec(html);
    if (ogMatch) {
      try {
        return new URL(ogMatch[1], origin).toString();
      } catch {}
    }

    return new URL('/favicon.ico', origin).toString();
  } catch {
    return siteUrl.endsWith('/favicon.ico') ? siteUrl : `${siteUrl}/favicon.ico`;
  }
}

function guessExt(contentType: string | null, iconUrl: string): string {
  const fromType = (type: string) => {
    const t = type.toLowerCase();
    if (t.includes('png')) return 'png';
    if (t.includes('jpeg')) return 'jpg';
    if (t.includes('jpg')) return 'jpg';
    if (t.includes('gif')) return 'gif';
    if (t.includes('webp')) return 'webp';
    if (t.includes('svg')) return 'svg';
    if (t.includes('x-icon') || t.includes('vnd.microsoft.icon')) return 'ico';
    return '';
  };
  const byType = contentType ? fromType(contentType) : '';
  if (byType) return byType;
  try {
    const url = new URL(iconUrl);
    const ext = url.pathname.split('.').pop()?.toLowerCase();
    if (ext) return ext;
  } catch {}
  return 'ico';
}

// 抓取站点标题与简介（title / meta description / og:title / og:description）
async function extractSiteMeta(siteUrl: string): Promise<{ title?: string; description?: string }> {
  try {
    const html = await downloadText(siteUrl);
    if (!html) return {};
    const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
    const title = titleMatch?.[1]?.trim();

    const descNameMatch = html.match(/<meta[^>]+name=["']description["'][^>]*content=["']([^"']+)["'][^>]*>/i);
    const ogTitleMatch = html.match(/<meta[^>]+property=["']og:title["'][^>]*content=["']([^"']+)["'][^>]*>/i);
    const ogDescMatch = html.match(/<meta[^>]+property=["']og:description["'][^>]*content=["']([^"']+)["'][^>]*>/i);

    const description = (descNameMatch?.[1] || ogDescMatch?.[1] || '').trim();
    return { title: title || ogTitleMatch?.[1]?.trim(), description };
  } catch {
    return {};
  }
}

// 上传图标并创建 File 记录，返回 fileId
async function uploadIcon(buffer: Buffer, contentType: string | null, iconUrl: string): Promise<string | null> {
  try {
    const ext = guessExt(contentType, iconUrl);
    const objectKey = `icon_${randomUUID()}.${ext}`;
    const stored = await uploadFile(buffer, objectKey, 'icons/');
    const record = await prisma.file.create({
      data: {
        provider: 'minio',
        bucket: process.env.MINIO_BUCKET_NAME || 'kason-world',
        path: stored.path,
        url: stored.url,
        mimeType: stored.mimeType,
        size: stored.size,
        visibility: 'public',
        category: 'amazing-website-icon',
        source: 'amazing-website-seed',
        status: 'active',
      },
    });
    return record.id;
  } catch (e) {
    console.warn('上传图标失败:', e);
    return null;
  }
}

// 站点图标抓取：先抓 HTML 解析 icon，再下载图标
async function fetchAndUploadSiteIcon(siteUrl: string): Promise<string | null> {
  try {
    let html = await downloadText(siteUrl);
    let iconUrl = '';
    if (html) {
      iconUrl = resolveIconUrl(html, siteUrl);
    } else {
      try {
        iconUrl = new URL('/favicon.ico', siteUrl).toString();
      } catch {
        return null;
      }
    }
    const iconResult = await downloadToBuffer(iconUrl);
    if (!iconResult) {
      // 兜底再次尝试 favicon.ico
      const fallback = new URL('/favicon.ico', siteUrl).toString();
      const fb = await downloadToBuffer(fallback);
      if (!fb) return null;
      return await uploadIcon(fb.buffer, fb.contentType, fallback);
    }
    return await uploadIcon(iconResult.buffer, iconResult.contentType, iconUrl);
  } catch {
    return null;
  }
}

// 获取或创建分类
async function getOrCreateCategory(name: string, menuId: string): Promise<string> {
  const existing = await prisma.category.findFirst({ where: { name, menuId } });
  if (existing) return existing.id;
  const created = await prisma.category.create({ data: { name, menuId } });
  return created.id;
}

// 创建/更新内容（包含自动元信息与图标抓取）
async function createOrUpdateContent(site: { name: string; url: string; description: string }, categoryId: string): Promise<void> {
  // 查重：优先按 URL，其次按标题 + type=1（网站）
  const existingByUrl = await prisma.content.findFirst({ where: { url: site.url } });
  const meta = await extractSiteMeta(site.url);

  const titleToUse = (meta.title && meta.title.length > 1 ? meta.title : site.name).trim();
  const descToUse = (meta.description && meta.description.length > 10 ? meta.description : site.description).trim();

  let coverId: string | null = null;
  try {
    coverId = await fetchAndUploadSiteIcon(site.url);
  } catch {}

  if (existingByUrl) {
    await prisma.content.update({
      where: { id: existingByUrl.id },
      data: {
        title: titleToUse,
        content: descToUse,
        summary: descToUse,
        type: 1,
        coverId: coverId || existingByUrl.coverId || null,
      },
    });
    // 确保分类关联存在
    const rel = await prisma.contentCategory.findFirst({ where: { contentId: existingByUrl.id, categoryId } });
    if (!rel) {
      await prisma.contentCategory.create({ data: { contentId: existingByUrl.id, categoryId } });
    }
    console.log(`✏️  已更新：${titleToUse}`);
    return;
  }

  const created = await prisma.content.create({
    data: {
      title: titleToUse,
      content: descToUse,
      summary: descToUse,
      url: site.url,
      type: 1,
      coverId: coverId || null,
    },
  });
  await prisma.contentCategory.create({ data: { contentId: created.id, categoryId } });
  console.log(`✅ 已创建：${titleToUse}`);
}

// 创建/获取菜单（sysCode: amazing-website）
async function ensureAmazingWebsiteMenu() {
  const sysCode = 'amazing-website';
  const existing = await prisma.menu.findFirst({ where: { sysCode } });
  if (existing) return existing;
  const created = await prisma.menu.create({
    data: {
      name: '神奇的网站',
      path: '/amazing-website',
      sysCode,
      isActive: 1,
    },
  });
  return created;
}

async function seedAmazingWebsite() {
  console.log('🚀 开始初始化“神奇的网站”（amazing-website）...');
  const menu = await ensureAmazingWebsiteMenu();
  console.log(`📋 菜单就绪：${menu.name} (${menu.id})`);

  // 先按分类名收集
  const categories = Array.from(new Set(WEBSITES.map((w) => w.category)));
  const categoryIdMap: Record<string, string> = {};
  for (const cname of categories) {
    const id = await getOrCreateCategory(cname, menu.id);
    categoryIdMap[cname] = id;
    console.log(`📂 分类就绪：${cname} -> ${id}`);
  }

  // 写入内容
  for (const site of WEBSITES) {
    const cid = categoryIdMap[site.category];
    await createOrUpdateContent(site, cid);
    // 轻微延时，避免高频请求（尤其是图标抓取）
    await new Promise((r) => setTimeout(r, 250));
  }

  console.log('🎉 初始化完成！已创建/更新站点数量：', WEBSITES.length);
}

async function main() {
  try {
    await seedAmazingWebsite();
  } catch (e) {
    console.error('❌ 脚本执行失败：', e);
    process.exitCode = 1;
  } finally {
    await prisma.$disconnect();
  }
}

if (require.main === module) {
  main();
}

export { seedAmazingWebsite };